﻿namespace Home.Services.SecurityService
{
    using System;
    using System.Data.Entity;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Security.Claims;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web.Http;
    using System.Web.OData;
    using System.Web.OData.Query;
    using System.Web.OData.Routing;

    public class UsersController : BaseODataController
    {
        private readonly SecurityDbContext database = new SecurityDbContext();

        // GET odata/Users
        [HttpGet]
        [EnableQuery(PageSize = 50)]
        public IHttpActionResult Get()
        {
            var users = this.database.Users.Where(r => !r._IsLocked);
            return Ok(users);
        }

        // GET odata/Users('id')
        [HttpGet]
        [EnableQuery]
        [ODataRoute("Users({id})")]
        public Task<IHttpActionResult> Get([FromODataUri] Guid id, ODataQueryOptions<User> options)
        {
            var users = this.database.Users.Where(r => r.Id == id && !r._IsLocked);
            return GetODataSingleAsync(users, options);
        }

        // GET odata/Users('id')/Property
        [HttpGet]
        [ODataRoute("Users({id})/LoginName")]
        [ODataRoute("Users({id})/DisplayName")]
        [ODataRoute("Users({id})/Role")]
        [ODataRoute("Users({id})/Created")]
        [ODataRoute("Users({id})/CreatedBy")]
        [ODataRoute("Users({id})/Modified")]
        [ODataRoute("Users({id})/ModifiedBy")]
        public async Task<IHttpActionResult> GetProperty([FromODataUri] Guid id)
        {
            var user = await this.database.Users.FirstOrDefaultAsync(r => r.Id == id && !r._IsLocked);
            return GetODataProperty(user);
        }

        [HttpPost]
        [ODataRoute("Login(name={name}, password={password})")]
        public async Task<IHttpActionResult> Login(string name, string password)
        {
            if (name == null || password == null)
            {
                return PreconditionRequired();
            }

            if (name.Length == 0 || password.Length == 0)
            {
                return StatusCode(HttpStatusCode.PreconditionFailed);
            }

            var values = await this.database.Users.Where(u => u.LoginName == name && !u._IsLocked)
                .Select(u => new { u.DisplayName, u.Role, Password = u._Password })
                .FirstOrDefaultAsync();
            if (values == null)
            {
                return StatusCode(HttpStatusCode.PreconditionFailed);
            }

            if (password != values.Password)
            {
                return StatusCode(HttpStatusCode.PreconditionFailed);
            }

            var identity = new ClaimsIdentity("Forms");
            identity.AddClaim(new Claim(ClaimTypes.Name, values.DisplayName));
            identity.AddClaim(new Claim(ClaimTypes.Role, values.Role.ToString()));
            Request.GetOwinContext().Authentication.SignIn(identity);

            return Ok(new LoginResult() { Name = values.DisplayName, Role = values.Role.ToString() });
        }

        [HttpPost]
        [ODataRoute("Login()")]
        public IHttpActionResult Logout()
        {
            Request.GetOwinContext().Authentication.SignOut("Forms");

            return Ok();
        }

        [HttpGet]
        [ODataRoute("CheckLogin()")]
        public IHttpActionResult CheckLogin()
        {
            var result = new LoginResult();

            var user = Request.GetOwinContext().Authentication.User;
            if (user.Identity.IsAuthenticated)
            {
                result.Name = user.Identity.Name;
                result.Role = user.FindFirst(ClaimTypes.Role).Value;
            }

            return Ok(result);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                this.database.Dispose();
            }

            base.Dispose(disposing);
        }
    }
}
